package algorithm;

import enumMsg.ProState;
import pojo.ProcessPojo;
import utils.TimeUtils;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.Random;
import java.util.Scanner;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
//基于优先级的调度算法
//本算法又分为抢占式以及非抢占式优先级调度算法
//非抢占式算法:初始化即确定好进程的优先级,根据优先级一直执行下去
//抢占式算法则是动态的，在进程运行中如果出现其他优先级更高的进程，则会停止当前运行进程转而运行另一个进程
//设计思路:可以先初始化一批进程,并且提供接口进行模拟产生新的优先级较高的进程,当产生更高优先级的进程时,
//系统停止当前进程的运行转而去运行另一个进程。
//为产生进程运行的效果,使用计时来进行模拟运行时的状态,
public class Priority {
	private volatile LinkedList<ProcessPojo> readyQueue;//就绪队列
	private ArrayList<ProcessPojo>runList;//运行时队列(使用)
	private volatile int size;
	private volatile int cnt;
	public void init(int n){
		//初始化n个进程，基于优先级的调度
		this.size=n;
		this.cnt=0;
		
		readyQueue=new LinkedList<>();
		Random random=new Random();
		for(int i=1;i<=n;i++){
			ProcessPojo pcb=new ProcessPojo();
			pcb.setState(ProState.READY.getState());//默认为就绪状态
			pcb.setName("进程->"+i);
			pcb.setCpuTime(0);//初始化cputime为0
			pcb.setNeedTime(random.nextInt(9)+1);//随机数设置所需时间
//			pcb.setOrder(i);//设置优先级
			pcb.setOrder(random.nextInt(9)+1);
			TimeUtils timeUtils=new TimeUtils(true);//设置模拟程序
			pcb.setTimeUtils(timeUtils);
			readyQueue.addLast(pcb);//尾插进程
		}

		readyQueue.sort(new Comparator<ProcessPojo>() {
			//根据优先级排序
			@Override
			public int compare(ProcessPojo o1, ProcessPojo o2) {
				return o1.getOrder()- o2.getOrder();
			}
		});
	}
	public  void addProcess(ProcessPojo processPojo){
		//插入进程
		this.cnt=1;
		this.readyQueue.add(processPojo);
		this.size++;
		readyQueue.sort(new Comparator<ProcessPojo>() {
			//根据优先级排序
			@Override
			public int compare(ProcessPojo o1, ProcessPojo o2) {
				return o1.getOrder()- o2.getOrder();
			}
		});
	}
	public void start(){
		//算法开始
		this.runList=new ArrayList<>();
		//如果直接遍历！在另一个线程添加时，会导致发生.ConcurrentModificationException异常
		//即对集合遍历的时候不可同时修改，所以要改变思路。采用一个一个弹出的方式
		ProcessPojo processPojo = this.readyQueue.getFirst();
		TimeUtils timeUtils = processPojo.getTimeUtils();
		String state = processPojo.getState();
		int order = processPojo.getOrder();
		String name = processPojo.getName();
		long needTime = processPojo.getNeedTime();
		long cpuTime = processPojo.getCpuTime();
		System.out.println("现在运行的程序是:"+name);
		System.out.println("优先级:"+order);
		System.out.println("所需时间:"+needTime);
		state=ProState.RUN.getState();
		System.out.println("当前状态"+state);
		
		if(this.cnt==0) {
			 long start = System.currentTimeMillis();	        
		        while (this.cnt==0&&System.currentTimeMillis()-start<=(needTime*1000)){
		        	
		        }
		        if(this.cnt==1&&System.currentTimeMillis()-start<=(needTime*1000)){
//		        	ProcessPojo pcb=new ProcessPojo();
		        	//保存现场工作
		        	processPojo.setState(ProState.READY.getState());//修改进程状态
		            long end=System.currentTimeMillis()-start;
		            processPojo.setCpuTime(Math.round((end/1000)));
		            processPojo.setNeedTime(processPojo.getNeedTime()-processPojo.getCpuTime());
//		            pcb.setName(processPojo.getName());
//		            pcb.setOrder(processPojo.getOrder());
//		            addProcess(pcb);
		            //保存现场工作
		            runList.add(processPojo);
		            
		            System.out.println("检测到抢占进程...");
					timeUtils.setFlag(false);
					this.cnt=0;
					System.out.println("终止目前进程"+name);
					System.out.println("剩余时间.."+processPojo.getNeedTime());
					return;
		        }
		}
		state=ProState.FINISH.getState();
		System.out.println(name+" 运行完毕..."+"当前状态为"+state);
		processPojo.setState(state);
		processPojo.setCpuTime(needTime);
		runList.add(processPojo);
		readyQueue.removeFirst();//用完即弃
		this.size--;
	}
	public ArrayList<ProcessPojo> getRunList() {
		return runList;
	}
	public void setRunList(ArrayList<ProcessPojo> runList) {
		this.runList = runList;
	}
	public int getSize() {
		return size;
	}
	public void setSize(int size) {
		this.size = size;
	}
	public int getCnt() {
		return cnt;
	}
	public void setCnt(int cnt) {
		this.cnt = cnt;
	}
	public void go(){
		Scanner scanner=new Scanner(System.in);
		System.out.println("请输入进程数..");
		int n = scanner.nextInt();
		System.out.println("开始模拟基于优先级调度的进程算法..");
		init(n);
		new Thread(()->{
			//开启一个线程来模拟跑程序
			start();
		}).start();
		new Thread(()->{
			//开启另一个线程来模拟提示用户添加进程
			System.out.println("========================");
			System.out.println("现在可以模拟添加进程...");
			System.out.println("输入1可以添加进程...");
			System.out.println("========================");
			int p= scanner.nextInt();
			scanner.close();
//			int p=1;
			if (p==1){
				this.cnt=1;
				ProcessPojo pcb=new ProcessPojo();
				pcb.setName("newpcb");
				pcb.setState(ProState.READY.getState());//默认为就绪状态
				pcb.setCpuTime(0);//初始化cputime为0
				pcb.setNeedTime(3);//随机数设置所需时间
				pcb.setOrder(1);
				TimeUtils timeUtils=new TimeUtils(true);//设置模拟程序
				pcb.setTimeUtils(timeUtils);
				this.addProcess(pcb);
				System.out.println("添加进程成功!!!");
				this.size++;
			}
		}).start();

	}
	public LinkedList<ProcessPojo> getReadyQueue() {
		return readyQueue;
	}



	public void setReadyQueue(LinkedList<ProcessPojo> readyQueue) {
		this.readyQueue = readyQueue;
	}

	public static void main(String[] args) throws InterruptedException {
		Priority priority=new Priority();
		priority.go();

	}

}
